iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 7
3

Firebase Functions 是 Firebase 服務中的其中一個功能,利用程式碼將這些事件透過 Functions 來處理並得到回應,典型的使用範例大概可以分成以下幾類:

  • 當有事件發生時傳送通知給用戶。
  • 執行 Realtime Database 的清理與維護
  • 在雲端執行密集型的任務,而非在自己的應用程式中。
  • 結合第三方服務與 API

以上四種使用範例的詳細說明可以參考:https://firebase.google.com/docs/functions/use-cases

要開始安裝並使用 Firebase Functions 功能之前要先開啟一個 Firebade 的專案來使用。
網站:https://firebase.google.com/
登入後就可以建立專案,專案建立成功就會到以下的畫面,也就是專案的控制面版

安裝

要使用 Firebase Functions 的功能需要先設置 Node.js 和 Firebase CLI

安裝 Node.js

網站:https://nodejs.org/en/

到網站上下載 Node.js 就可以安裝了,Cloud Functions 可以在 Node v6 或 Node v8 上運行。如果你本來就是使用 v6 的版本就可以直接繼續使用,不需要升級成 Node v8。

安裝 Firebase 工具:

$ npm install -g firebase-tools

如果之前已經安裝過 Firebase 指令列工具,還是會建議再次執行一次安裝的指令,這樣可以確保安裝的是最新的版本。

初始化 Firebase SDK for Cloud Functions

初始化 Firebase SDK for Cloud Functions 的時候,會建立一個專案,裡面包含了範例代碼,初始化時也可以選擇要使用 TypeScript 或 JavaScript 來編寫。

在終端機輸入

firebase init

接下來就會被詢問很多個問題,大多都可以依照個人要使用的程度來回答,其中包括選擇要 JavaScript 或是 TypeScript。選擇 JavaScript 後還會詢問是否安裝 ESlint 與 npm 模組。

初始化成功完成之後至少會出現紅色框框中的檔案,如果有這些檔案就代表初始化的步驟已經成功:

導入所需要的模組並初始化應用

這邊跟著 Firebase 範例,是使用 Node require 語句來導入 Cloud Functions 和 Admin SDK 這兩個模塊。請將下面的代碼貼到 index.js

// The Cloud Functions for Firebase SDK to create Cloud Functions and setup triggers.
const functions = require('firebase-functions');

// The Firebase Admin SDK to access the Firebase Realtime Database.
const admin = require('firebase-admin');
admin.initializeApp();

這幾行程式碼會載入 firebase-functions 和 firebase-admin 模塊並初始化一個可以即時更改 database 的 admin 應用範例。

加入 addMessage() 函式

加入 addMessage() 函式,請將程式碼加入到 index.js:

// 抓取要傳遞給此 HTTP 端點的 text 參數值並將這個值新增到 Realtime Database 下的路徑 
`/messages/:pushId/original`
exports.addMessage = functions.https.onRequest((req, res) => {
  const original = req.query.text; //抓取訊息內容
  // 使用 Firebase Admin SDK 將訊息新增到 Realtime Database
  return admin.database().ref('/messages').push({original: original}).then((snapshot) => {
    return res.redirect(303, snapshot.ref.toString());
  });
});

HTTP 函數是同步函式,addMessage()會向這個端點傳遞一個 text 的值,並使用前一個步驟初始化的 admin 將這個 text 的值新增到 Realtime Database 下的路徑:/messages/:pushId/original

部署和執行 addMessage()

了解了 addMessage() 的作用,我們就要來將這個函式部署與執行,讓它真的可以透過 Firebase Functions 的功能來做新增:

在終端機輸入這一段

$ firebase deploy --only functions

輸入這行指令之後,Firebase CLI 會輸出一個 HTTP 函數端點的網址:

Function URL (addMessage): https://us-central1-你的專案名稱.cloudfunctions.net/addMessage

到 Firebase Functions 的面板,可以看到這個畫面,也就是成功將添增訊息的函式成功放到 Functions 上,之後就可透過 Function 將監聽資料庫改變,下面就來透過 Function 來傳送訊息至資料庫。

在剛剛獲取的 addMessage() 網址後面加上 text 參數值,並在瀏覽器打開這個網址:

輸入後會跳轉至控制面板,可以看到 Realtime Database 有新增資料,也就是剛剛在網址最後面輸入的訊息內容,且路徑也和我們設定的相同是在 /messages/:pushId/original
這邊的 :pushId 是由 Firebase 隨機產生的 ID,將來也可以透過這個 ID 來搜索資料

成功將訊息推上 Realtime Database 也可以看到剛剛新增在 Functions 中的 addMessage 函式紀錄,有出現 console 的內容

到這邊就成功新增一個函式,接下來我們新增其他的函式來更加了解 Functions 的運作

加入 makeUppercase() 函式

exports.makeUppercase = functions.database.ref('/messages/{pushId}/original')
    .onCreate((snapshot, context) => {
      const original = snapshot.val();
      console.log('Uppercasing', context.params.pushId, original);
      const uppercase = original.toUpperCase();
      return snapshot.ref.parent.child('uppercase').set(uppercase);
    });

makeUppercase() 函式會在有數據寫入 Realtime Database 執行。ref(path) 則是用來定義要監聽 Database 的哪個部分。每當指定的路徑中有資料寫入或是更新時, Realtime Database 都會觸發 onWrite() 這個函數

使用 onWrite() 時要特別注意避免出現無限循環的情況,也就是函式執行後的結果會再重新觸發該函式。此外,在編寫函式時也需要遵守 idempotent 原則,idempotent 的意思是如果相同的操作再執行第二遍第三遍,結果還是跟第一遍的結果一樣,也就是說不管執行了幾次結果都和執行一次是一樣的,遵守此原則是為了單一個事件如果多次使用這個函數還是可以產生相同結果。

部署和執行 makeUppercase()

要部署和執行函式都一定要在終端機輸入:

$ firebase deploy --only functions

部署成功後一樣會在 Firebase Functions 中看到新增的 makeUppercase() 函式:

測試

一樣在網址上最後輸入訊息:

當訊息透過 HTTP 端點新增到 Realtime Database 時, makeUppercase() 會讀取到 /messages/{pushId}/original 這個路徑下有新增,就會同時觸發 makeUppercase() 將讀取到的字串轉成大寫並一起傳送入 Realtime Database。

到這一步對於 Firebase Functions 已經有初步的了解,Firebase Functions 簡化了傳送至資料庫之前的資料處理過程,下一篇我們就再更詳細的說明 Firebase Functions 觸發 Realtime Database 的函式,並再介紹實例應用。


上一篇
MarkMan - 高效的設計稿標註與測量工具
下一篇
Firebase Functions - 實現 Serverless(下)
系列文
前端工具百寶箱 - 六角學院30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言